///<reference path='../troop-types.ts' />
///<reference path='../utilities.ts' />
///<reference path='../army-types.ts'/>
///<reference path='../exceptions.ts'/>

declare function test(testName: string, testFunc: () =>void );
declare function ok(isOk: bool, errorMessage: string);
declare function throws(block: () =>void , expected: any, message: string);

function SetupDiamyoArmy(): DiamyoArmy{
    return new DiamyoArmy("Test");
}

function AddSwordmen(army: IArmy, numSwordmen: number) {
    for (var count: number = 0; count < numSwordmen; ++count)
        army.AddTroop(new Troop(TroopTypes.SamuraiSwordman));
}

function AddRonin(army: IArmy, numRonin: number) {
    for (var count: number = 0; count < numRonin; ++count)
        army.AddTroop(new Troop(TroopTypes.Ronin));
}

test("DiamyoArmy Swordman Added getAllTroops contains 1 item", function(){
    var testArmy:DiamyoArmy = SetupDiamyoArmy();
    testArmy.AddTroop(new Troop(TroopTypes.SamuraiSwordman));
    ok(testArmy.getAllTroops().length == 1, "AllTroops should have a length of 1");
});

test("DiamyoArmy Swordman Added getAllTroops contains swordman", function(){ 
    var testArmy: DiamyoArmy = SetupDiamyoArmy(); 
    testArmy.AddTroop(new Troop(TroopTypes.SamuraiSwordman));
    ok(testArmy.getAllTroops()[0].TroopType == TroopTypes.SamuraiSwordman, "AllTroops should have a single troop of type SamuraiSwordMan");
});

test("DiamyoArmy No troops added, RoninSlotAvailable is false", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    ok(!testArmy.getRoninSlotsAvailable(), "No Ronin Slots should be available");
});

test("DiamyoArmy One Swordman added, RoninSlotAvailable is false", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    ok(!testArmy.getRoninSlotsAvailable(), "No Ronin Slots should be available");
});

test("DiamyoArmy Two Swordmen added, RoninSlotAvailable is true", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 2);
    ok(testArmy.getRoninSlotsAvailable(), "Ronin Slots should be available");    
});

test("DiamyoArmy no troops added, canRemoveShogunTroop is false", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    ok(!testArmy.getCanRemoveShogunTroop(), "canRemoveShogunTroop should be false");
});

test("DiamyoArmy one Swordman troop added, canRemoveShogunTroop is true", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 1);
    ok(testArmy.getCanRemoveShogunTroop(), "canRemoveShogunTroop should be true");
});

test("DiamyoArmy three Swordmen troops added and one Ronin added, canRemoveShogunTroop is true", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 3);
    AddRonin(testArmy, 1);
    ok(testArmy.getCanRemoveShogunTroop(), "canRemoveShogunTroop should be true");
});

test("DiamyoArmy two Swordmen added and one Ronin added, canRemoveShogunTroop is false", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 2);
    AddRonin(testArmy, 1);
    ok(!testArmy.getCanRemoveShogunTroop(), "canRemoveShogunTroop should be false");
});

test("DiamyoArmy two Swordmen added, one Swordman Removed. Only One Swordman remains", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 2);
    testArmy.RemoveTroopByType(TroopTypes.SamuraiSwordman);
    ok(testArmy.getAllTroops().length == 1, "Swordman was not removed");
});

test("DiamyoArmy three Swordmen troops added and one Ronin added Swordman is removed, canRemoveShogunTroop is false", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 3);
    AddRonin(testArmy, 1);
    testArmy.RemoveTroopByType(TroopTypes.SamuraiSwordman);
    ok(!testArmy.getCanRemoveShogunTroop(), "canRemoveShogunTroop should be false.");
});

test("DiamyoArmy two Swordmen troops added and one Ronin added, Ronin is removed, canRemoveShogunTroop is true", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 2);
    AddRonin(testArmy, 1);
    testArmy.RemoveTroopByType(TroopTypes.Ronin);
    ok(testArmy.getCanRemoveShogunTroop(), "canRemoveShogunTroop should be true.");
});

test("DiamyoArmy two Swordmen troops added and one Ronin added, Ronin is removed then shogun troop removed, canRemoveShogunTroop is true", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 2);
    AddRonin(testArmy, 1);
    testArmy.RemoveTroopByType(TroopTypes.Ronin);
    testArmy.RemoveTroopByType(TroopTypes.SamuraiSwordman);
    ok(testArmy.getCanRemoveShogunTroop(), "canRemoveShogunTroop should be true.");
});

test("DiamyoArmy no troops added. Attempts to remove a shogun troop, TroopConstraintViolationException thrown", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    throws(function () {
        testArmy.RemoveTroopByType(TroopTypes.SamuraiSwordman);
    },
    TroopConstraintViolationException,
    "Expected TroopConstraintViolcationException to be thrown");
});

test("DiamyoArmy Swordman added. Attempts to remove Bowman, TroopConstraintViolationException thrown", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    testArmy.AddTroop(new Troop(TroopTypes.SamuraiSwordman));
    throws(function () {
        testArmy.RemoveTroopByType(TroopTypes.SamuraiBowman);
    },
    TroopConstraintViolationException,
    "Expected TroopConstraintViolationException to be thrown");
});

test("DiamyoArmy two Swordmen troops added and one Ronin added, attempts to remove Shogun troop, TroopConstraintViolationException thrown", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 2);
    AddRonin(testArmy, 1);

    throws(function () {
        testArmy.RemoveTroopByType(TroopTypes.SamuraiSwordman);
    },
    TroopConstraintViolationException,
    "Expected TroopContraintViolationException to be thrown");
});

test("No troops added DiamyoArmy, getCanRemoveTroopByType(TroopTypes.SamuraiSwordmen) returns false", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    ok(!testArmy.getCanRemoveTroopByType(TroopTypes.SamuraiSwordman), "should be false");
});

test("DiamyoArmy No troops added, getCanRemoveTroopByType(TroopTypes.Ronin) returns false", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    ok(!testArmy.getCanRemoveTroopByType(TroopTypes.Ronin), "false expected");
});

test("DiamyoArmy two Swordmen troops added, getCanRemoveTroopByType(TroopTypes.SamuraiSwordmen) returns true", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 2);
    ok(testArmy.getCanRemoveTroopByType(TroopTypes.SamuraiSwordman), "true expected");
});

test("DiamyoArmy three Swordmen troops added and two Ronin troops, getCanRemoveTroopByType(TroopTypes.Ronin) returns true", function () {
    var testArmy: DiamyoArmy = SetupDiamyoArmy();
    AddSwordmen(testArmy, 3);
    AddRonin(testArmy, 2);
    ok(testArmy.getCanRemoveTroopByType(TroopTypes.Ronin), "true expected");
});